﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MvvmFoundation.Wpf;
using System.Windows.Input;
using GroundStation.Models;
using GroundStation.Models.Launcher;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.IO.Pipes;
using System.Security.Principal;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using Microsoft.Win32;

namespace GroundStation.ViewModels
{
    /// <summary>
    /// This class is the login screen/chat/Launcher view model. It allows the user to open Gpredict, open the station console, and communicate with others logged in
    /// 
    ///***This viewmodel assumes that you have a chat server up and running somewhere, the setting will allow you to run this on a different computer with a different IP
    ///to host the chat server.
    ///
    /// GPREDICT is hardcoded with the current location on our local machine, this will need to be changed to a common location, or a setting to allow users to choose the path
    /// 
    /// </summary>
    class MainWindowViewModel:ViewModelBase
    {
        private ICommand _authenticateCommand, _openKissKonsoleCommand, _openSDTCommand, _sendMessageCommand, _openGPredictCommand;
        private User _user;
       
        //constructor
        public MainWindowViewModel()
        {
            
        }
        
        //callsign binding to a textbox
        public string CallSign
        {
            get;
            set;
        }
        //bandwidth binding to a textbox
        public string Bandwidth
        {
            get;
            set;
        }
        public string MessageText
        {
            get;
            set;
        }
        public string ChatConsole
        {
            get;
            set;
        }
        //once authenticated, associates with a user model
        public User User
        {
            get
            {
                return _user;
            }
            set
            {
                _user = value;
                OnPropertyChanged("User");
            }
        }
        public ICommand AuthenticateCommand
        {
            get
            {
                if (_authenticateCommand == null)
                    _authenticateCommand = new RelayCommand(() =>
                    {

                        User = User.GetUser(CallSign, Bandwidth);
                        if (User == null)
                        {
                            MessageBox.Show("Invalid Callsign, please try again");
                        }
                        else
                        {
                               BackgroundWorker bg = new BackgroundWorker();
                               bg.DoWork+=new DoWorkEventHandler(receiveMessageThread);
                               bg.WorkerReportsProgress = true;
                               bg.ProgressChanged+=new ProgressChangedEventHandler(messageReceived);
                               bg.RunWorkerAsync();
                        }
                    }, () =>
                    {
                        if((CallSign!=null && CallSign!="") && (Bandwidth!=null && Bandwidth!=""))
                            return true;
                        return false;
                    });
                
                return _authenticateCommand;
            }
        }
        //listen to the chat server for new messages
        private void receiveMessageThread(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bg = sender as BackgroundWorker;
            StreamReader sr = new StreamReader(User.TcpClient.GetStream());
            string message;
            try
            {
                while (true)
                {
                    while ((message = sr.ReadLine()) != "")
                    {
                        bg.ReportProgress(0, message);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("The chat server has unexpectibly quit");
                User = null;
                OnPropertyChanged("User");
            }
        }
        //update chat box
        private void messageReceived(object sender, ProgressChangedEventArgs e)
        {
            ChatConsole += e.UserState.ToString()+"\n";
            OnPropertyChanged("ChatConsole");
        }
        public ICommand OpenKissKonsoleCommand
        {
            get
            {
                if (_openKissKonsoleCommand == null)
                    _openKissKonsoleCommand = new RelayCommand(() =>
                    {
                        //insert code here

                    }, () =>
                    {
                        if (User != null)
                            return true;
                        return false;
                    });

                return _openKissKonsoleCommand;
            }
        }

       
        public ICommand OpenSDTCommand
        {
            get
            {
                if (_openSDTCommand == null)
                    _openSDTCommand = new RelayCommand(() =>
                    {
                        
                        Views.StationConsoleView consoleView = new Views.StationConsoleView();
                        StationConsoleViewModel vm = new StationConsoleViewModel(User);
                        consoleView.DataContext = vm;

                        consoleView.Show();
                           

                    }, () =>
                    {
                        if (User != null && !Views.StationConsoleView.IsOpen)
                            return true;
                        return false;
                    });

                return _openSDTCommand;
            }
        }
        public ICommand OpenGPredictCommand
        {
            get
            {
                if (_openGPredictCommand == null)
                    _openGPredictCommand = new RelayCommand(() =>
                    {

                        Process.Start(@"C:\Users\Mike\Desktop\FinalSeniorProject\gpredict-win32-1.3-3\gpredict-win32-1.3-3\bin\GPredict.exe");

                    }, () =>
                    {
                        if (User != null)
                            return true;
                        return false;
                    });

                return _openGPredictCommand;
            }
        }





            
        public ICommand SendMessageCommand
        {
            get
            {
                if (_sendMessageCommand == null)
                    _sendMessageCommand = new RelayCommand(() =>
                    {

                        StreamWriter sw = new StreamWriter(User.TcpClient.GetStream());
                        sw.WriteLine(MessageText);
                        sw.Flush();
                        MessageText = "";
                        OnPropertyChanged("MessageText");
                        
                    }, () =>
                    {
                        if (User != null && MessageText!=null && MessageText!="" )
                            return true;
                        return false;
                    });

                return _sendMessageCommand;
            }
        }

        //this portion currently isn't used because we had to switch our software to use POWERSDR instead of kiss konsole.
        public void KissKonsolePipingThreadStart(object sender, DoWorkEventArgs e)
        {
            //Initialize the stream from Launcher to KISS Konsole
            NamedPipeServerStream pipeServer =
                new NamedPipeServerStream("kissPipe", PipeDirection.InOut, 1);
            int threadId = Thread.CurrentThread.ManagedThreadId;
            BackgroundWorker bg = sender as BackgroundWorker;

            //Send a Radio startup  message to Tower Top
            Message kkStartUpMessage = new KissKonsoleMessage();
            kkStartUpMessage.Status = 1;
            kkStartUpMessage.SetPayload("1");
            kkStartUpMessage.SendMessage();

            //Initialize the listener for communication with Tower Top
            TcpListener responseListener = new TcpListener(1989);
            responseListener.Start();
            TcpClient towerTop = responseListener.AcceptTcpClient();

            //Start getting data from Tower Top
            StreamReader responseStream = new StreamReader(towerTop.GetStream());
            pipeServer.WaitForConnection();
            String response;
            while (true)
            {
                try
                {
                    StreamString ss = new StreamString(pipeServer);

                    //Verifying the identity of the client
                    ss.WriteString("I am the one true server!");
                    string flexData="";

                    //Data is being read in from tower top here
                    response = responseStream.ReadLine();
                    bg.ReportProgress(0, response);

                    // Data is now sent to the KISS Konsole
                    ss.WriteString(flexData);
                }
                // Catch the IOException that is raised if the pipe is broken
                // or disconnected.
                catch (IOException ioe)
                {
                    Console.WriteLine("ERROR: {0}", ioe.Message);
                }
            }
            pipeServer.Close();
        }
    }
}
